(function($, window, document, undefined){

	var

	pluginName = "parallax",

	/* ------------------------------------------------------- */
	/* DEFAULT OPTIONS
	/* ------------------------------------------------------- */

	defaults = {
		xpos: "50%",
		offsety: 0,
		start: "100%", /* number of pixels from window top. when the top edge of the element passes this point, the parallax effect will start */
		stop: 0, /* number of pixels from window top. when the bottom edge of the element passes this point, the parallax effect will stop */
		span: 250, /* the total distance travelled by the image during the parallax effect */
	};

	$.extend($.fn, {

		parallax: function(options){
			
			/* ------------------------------------------------------- */
			/* PLUGIN
			/* ------------------------------------------------------- */

			var command = typeof options === "string",
			options	= command ? options : $.extend(true, {}, defaults, options),
			args 	= arguments;

			function parallax(target, options){
				this.target = target;
				this.options = $.extend(true, {}, options);
				this.options = this.dapi(this.target, this.options);
				this.update();

				$(window).on("scroll", {t: this}, this.reqUpdate).on("resize", {t: this}, this.reqUpdate);
			}

			parallax.prototype.dapi = function(target, options){
				for(var o in options){
					if(target.data((pluginName + "-" + o).toLowerCase()) !== undefined){
						options[o] = target.data((pluginName + "-" + o).toLowerCase());
					}
				}

				return options;
			}

			parallax.prototype.reqUpdate = function(e){
				e.data.t.update();
			}

			parallax.prototype.update = function(){
				clearTimeout(this.timeout);
				this.timeout = setTimeout((function(t){
					return function(){
						var target 		= t.target,
							o 			= t.options,
							top 		= target.offset().top,
							h 			= target.height(),
							wh 			= $(window).height(),
							st			= $(window).scrollTop(),
							ost 		= typeof o.start === "string" && o.start.slice(o.start.length - 1) == "%" ? parseInt(o.start)*wh/100 : o.start;
							oen 		= typeof o.stop === "string" && o.stop.slice(o.stop.length - 1) == "%" ? parseInt(o.stop)*wh/100 : o.stop;
							p 			= top - st,
							a			= p - ost,
							b			= p - oen + h,
							v 			= Math.min(0, Math.max(-1, a/(b - a))),
							d 			= v*o.span + o.offsety;

						target.css("background-position", o.xpos + " " + d + "px");
					}
				}(this)), 10);
			}

			if(command){
				/* execute command */
				switch(options){
					case "ACTION":
						// DO ACTION
						return;
				}
			}else{
				/* initialize plugin */
				return $(this).each(function(){
					var instance = new parallax($(this), options);
					$(this).get(0)["_" + pluginName + "Instance"] = instance;
				});
			}
		}

	});

}(jQuery, window, document));